package com.clei.utils.helper;

import com.clei.dto.file.FileName;
import com.clei.utils.CollectionUtil;
import com.clei.utils.FileUtil;
import com.clei.utils.PrintUtil;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * sql数据修改器
 * 默认导出的sql里的数据的insert是一条一条的，执行的时候很慢
 * 修改为批量insert
 *
 * @author Y
 * @date 2023-10-07
 **/
public class DataSqlUpdater {

    /**
     * 插入sql标记
     */
    private String insertMark = "INSERT INTO";

    /**
     * 插入sql values标记
     */
    private String valuesMark = "VALUES ";

    /**
     * 批量insert数据条数限制
     */
    private int dataLimit = 500;

    public static void main(String[] args) {
        new DataSqlUpdater("E:\\test\\test.sql");
    }

    public DataSqlUpdater(String sqlFile) {
        update(sqlFile);
    }

    public DataSqlUpdater(String sqlFile, String insertMark, String valuesMark, int dataLimit) {
        this.insertMark = insertMark;
        this.valuesMark = valuesMark;
        this.dataLimit = dataLimit;
        update(sqlFile);
    }

    /**
     * 修改
     *
     * @param sourceFilePath 源文件路径
     */
    public void update(String sourceFilePath) {
        FileName fileName = FileUtil.getFileName(sourceFilePath);
        // 输出文件路径 /a/b/c/test.sql -> /a/b/c/test_update.sql
        String outputFilePath = fileName.getParent()
                + File.separator
                + fileName.getName().replace(fileName.getSimpleName(), fileName.getSimpleName() + "_update");
        List<String> insertList = new ArrayList<>(dataLimit);
        // 修改
        try (FileReader fr = new FileReader(sourceFilePath);
             FileWriter fw = new FileWriter(outputFilePath);
             BufferedReader br = new BufferedReader(fr);
             BufferedWriter bw = new BufferedWriter(fw)) {
            // 局部变量
            String str;
            boolean insert = false;
            while (null != (str = br.readLine())) {
                boolean insertStr = str.startsWith(insertMark);
                if (insert) {
                    if (insertStr) {
                        insertList.add(str);
                        // 到达限制条数
                        if (dataLimit == insertList.size()) {
                            insert = false;
                            write(bw, insertList);
                        }
                    } else {
                        insert = false;
                        write(bw, insertList);
                        // insert 段落结束后
                        bw.write(str);
                        bw.newLine();
                    }
                } else {
                    // insert 开始
                    if (insertStr) {
                        insert = true;
                        insertList.add(str);
                    } else {
                        // 非insert语句
                        bw.write(str);
                        bw.newLine();
                    }
                }
            }
            // 剩余insert语句
            if (CollectionUtil.isNotEmpty(insertList)) {
                write(bw, insertList);
            }
            bw.flush();
        } catch (Exception e) {
            PrintUtil.log("sql数据修改出错 sourceFilePath : {}, dataLimit : {}", sourceFilePath, dataLimit, e);
        }
    }

    /**
     * 写入
     *
     * @param bw         BufferedWriter
     * @param insertList insert sql list
     * @throws IOException 写入异常
     */
    private void write(BufferedWriter bw, List<String> insertList) throws IOException {
        int size = insertList.size();
        String first = insertList.get(0);
        // 仅一条时不用处理 直接写入
        if (1 == size) {
            bw.write(first);
            bw.newLine();
        } else {
            int dataIndex = first.indexOf(valuesMark) + valuesMark.length();
            // 首行
            bw.write(first, 0, first.length() - 1);
            bw.write(',');
            bw.newLine();
            // 中间行
            for (int i = 1; i < size - 1; i++) {
                String sql = insertList.get(i);
                bw.write(sql.substring(dataIndex, sql.length() - 1));
                bw.write(',');
                bw.newLine();
            }
            // 尾行
            bw.write(insertList.get(size - 1).substring(dataIndex));
            bw.newLine();
        }
        // 清空
        insertList.clear();
    }
}
